import socket
import threading

# Port number to bind to
LISTENING_PORT = 6666

def manage_client_connection(client_socket, client_address):
    """
    Function to handle client connections in a separate thread.
    """
    try:
        while True:
            # Receive data from the client
            incoming_data = client_socket.recv(1024)
            if incoming_data:
                # Decode the received data from bytes to string
                incoming_message = incoming_data.decode("utf-8", "ignore")
                print(f'Data received from {client_address}: {incoming_message}')

                # Prepare the response message
                response_message = f'Acknowledged, client ({client_address[0]})! This is the server responding to your unique message.'
                # Send the response message to the client
                client_socket.send(response_message.encode('utf-8'))
            else:
                print(f'Connection closed by {client_address}')
                break
    except Exception as e:
        print(f'An error occurred: {e}')
    finally:
        # Close the client connection
        client_socket.close()

def launch_server():
    """
    Function to initialize the server and listen for incoming client connections.
    """
    # Create a TCP/IP socket
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server_socket:
        # Bind the socket to the specified port
        server_socket.bind(('', LISTENING_PORT))
        # Start listening for incoming connections
        server_socket.listen()
        print(f'TCP server is now listening on port {LISTENING_PORT}...')

        try:
            while True:
                # Accept an incoming client connection
                client_connection, client_address = server_socket.accept()
                print(f'Accepted connection from {client_address}')

                # Create a new thread to handle the client connection
                client_thread = threading.Thread(target=manage_client_connection, args=(client_connection, client_address))
                # Start the client handling thread
                client_thread.start()
        except (KeyboardInterrupt, Exception) as e:
            print(f'Server is shutting down due to an error: {e}')

if __name__ == '__main__':
    launch_server()
